package luke.media.video;

import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.javacv.*;
import org.bytedeco.javacv.Frame;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.List;
import javax.imageio.ImageIO;

import luke.system.callback.ProgressCallback;


/**
 * 播放列表叠加视频生成器类，用于在图片轮播视频上叠加播放列表。
 * 此类在图片轮播的基础上，使用VideoUIUtils绘制播放列表。
 */
public class PlaylistOverlayVideoGenerator {
    private List<String> imagePaths;
    private List<String> playlistContent;
    private String musicPath;
    private String outputVideoPath;
    private int width;
    private int height;
    private String videoTitle;

    public PlaylistOverlayVideoGenerator(List<String> imagePaths, List<String> playlistContent, String musicPath, String outputVideoPath, String videoTitle) {
        this(imagePaths, playlistContent, musicPath, outputVideoPath, videoTitle, 1920, 1080);
    }

    public PlaylistOverlayVideoGenerator(List<String> imagePaths, List<String> playlistContent, String musicPath, String outputVideoPath, String videoTitle, int width, int height) {
        this.imagePaths = imagePaths;
        this.playlistContent = playlistContent != null ? playlistContent : java.util.Collections.emptyList();
        this.musicPath = musicPath;
        this.outputVideoPath = outputVideoPath;
        this.width = width;
        this.height = height;
        this.videoTitle = videoTitle != null && !videoTitle.isEmpty() ? videoTitle : "播放列表";
    }

    /**
     * 生成带有音乐的视频，循环播放多张图片直到音频结束，并叠加播放列表。
     */
    public boolean generateVideoWithMultipleImagesAndPlaylist(double durationMs, double imageDisplayDurationMs) {
        return generateVideoWithMultipleImagesAndPlaylist(durationMs, imageDisplayDurationMs, null);
    }

    /**
     * 生成带有音乐的视频，循环播放多张图片直到音频结束，并叠加播放列表。
     */
    public boolean generateVideoWithMultipleImagesAndPlaylist(double durationMs, double imageDisplayDurationMs, ProgressCallback progressCallback) {
        if (imagePaths == null || imagePaths.isEmpty()) {
            System.err.println("没有可用的图片路径。");
            return false;
        }

        FFmpegFrameRecorder recorder = null;

        try {
            // 使用极低的帧率 - 1fps
            double fps = 1.0;
            double durationInSeconds = durationMs / 1000.0;
            double imageDisplayDurationInSeconds = imageDisplayDurationMs / 1000.0;

            // 计算需要的图片数量
            int totalImages = (int) Math.ceil(durationInSeconds / imageDisplayDurationInSeconds);
            System.out.println("总时长: " + durationInSeconds + "秒, 需要图片数量: " + totalImages);

            // 创建视频录制器
            recorder = new FFmpegFrameRecorder(outputVideoPath, width, height);
            recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
            recorder.setFormat("mp4");
            recorder.setFrameRate(fps);
            recorder.setPixelFormat(0);
            recorder.setVideoBitrate(1000000);

            // 设置音频参数
            if (musicPath != null && !musicPath.isEmpty()) {
                try {
                    FFmpegFrameGrabber audioGrabber = new FFmpegFrameGrabber(musicPath);
                    audioGrabber.start();
                    // 使用AAC编解码器而不是直接复制源音频的编解码器
                    recorder.setAudioCodec(org.bytedeco.ffmpeg.global.avcodec.AV_CODEC_ID_AAC);
                    recorder.setSampleRate(audioGrabber.getSampleRate());
                    recorder.setAudioChannels(audioGrabber.getAudioChannels());
                    recorder.setAudioBitrate(192000); // 设置固定的音频比特率192kbps
                    audioGrabber.stop();
                    audioGrabber.release();
                } catch (Exception e) {
                    System.err.println("设置音频参数失败: " + e.getMessage());
                }
            }

            // 启动录制器
            recorder.start();

            // 逐张处理图片
            for (int i = 0; i < totalImages; i++) {
                int imageIndex = i % imagePaths.size();
                String imagePath = imagePaths.get(imageIndex);

                Java2DFrameConverter converter = null;
                try {
                    // 为每张图片创建新的转换器实例
                    converter = new Java2DFrameConverter();

                    // 正确加载图片并转换为Frame
                    BufferedImage originalImage = ImageIO.read(new File(imagePath));

                    // 创建正确颜色格式的BufferedImage以避免发红问题
                    BufferedImage bufferedImage = new BufferedImage(
                            width,
                            height,
                            BufferedImage.TYPE_3BYTE_BGR);

                    // 绘制原始图像到正确格式的图像上（居中显示）
                    Graphics2D g2d = bufferedImage.createGraphics();
                    
                    // 启用抗锯齿
                    g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
                    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                    
                    // 计算居中位置
                    int imageWidth = originalImage.getWidth();
                    int imageHeight = originalImage.getHeight();
                    int x = (width - imageWidth) / 2;
                    int y = (height - imageHeight) / 2;
                    
                    // 绘制图片
                    g2d.drawImage(originalImage, x, y, null);
                    
                    // 绘制播放列表
                    VideoUIUtils.drawPlaylist(g2d, playlistContent, width, height, videoTitle);
                    
                    g2d.dispose();

                    // 释放原始图像资源
                    originalImage.flush();

                    Frame frame = converter.convert(bufferedImage);

                    // 重复记录同一帧来达到显示时长的效果
                    int repeatFrames = (int) Math.round(fps * imageDisplayDurationInSeconds);
                    repeatFrames = Math.max(1, repeatFrames);

                    for (int j = 0; j < repeatFrames; j++) {
                        recorder.record(frame);
                    }

                    // 立即释放资源
                    frame.close();
                    bufferedImage.flush();

                    // 每处理5张图片输出一次进度并进行GC
                    if (i % 5 == 0) {
                        double progress = (double) i / totalImages * 100;
                        System.out.printf("进度: %.1f%%, 已处理图片: %d/%d%n", progress, i, totalImages);

                        // 更新进度回调
                        if (progressCallback != null) {
                            progressCallback.onProgress("正在处理图片 " + (i+1) + "/" + totalImages, progress);
                        }

                        System.gc();
                        Thread.sleep(50);
                    }

                } catch (Exception e) {
                    System.err.println("处理图片 " + imagePath + " 时出错: " + e.getMessage());
                    e.printStackTrace();
                } finally {
                    // 确保转换器被正确关闭
                    if (converter != null) {
                        try {
                            converter.close();
                        } catch (Exception e) {
                            System.err.println("关闭转换器时出错: " + e.getMessage());
                        }
                    }
                }
            }

            // 复制音频轨道
            if (musicPath != null && !musicPath.isEmpty()) {
                System.out.println("开始复制音频轨道...");
                if (progressCallback != null) {
                    progressCallback.onProgress("正在复制音频轨道...", 90);
                }
                copyAudioTrackSimple(musicPath, recorder, progressCallback);
            }

            System.out.println("视频生成成功: " + outputVideoPath);
            if (progressCallback != null) {
                progressCallback.onProgress("视频生成完成", 100);
            }
            return true;

        } catch (Exception e) {
            System.err.println("视频生成失败: " + e.getMessage());
            e.printStackTrace();
            return false;
        } finally {
            // 确保所有资源都被正确释放
            try {
                if (recorder != null) {
                    recorder.stop();
                    recorder.release();
                }
            } catch (Exception e) {
                System.err.println("释放录制器资源时出错: " + e.getMessage());
            }

            System.gc();
        }
    }

    /**
     * 简化的音频复制方法
     */
    private void copyAudioTrackSimple(String audioPath, FFmpegFrameRecorder recorder) {
        copyAudioTrackSimple(audioPath, recorder, null);
    }

    /**
     * 简化的音频复制方法
     */
    private void copyAudioTrackSimple(String audioPath, FFmpegFrameRecorder recorder, ProgressCallback progressCallback) {
        FFmpegFrameGrabber audioGrabber = null;
        try {
            audioGrabber = new FFmpegFrameGrabber(audioPath);
            audioGrabber.start();

            Frame audioFrame;
            int count = 0;
            while ((audioFrame = audioGrabber.grabFrame()) != null) {
                if (audioFrame.samples != null) {
                    recorder.record(audioFrame);
                    count++;

                    if (count % 100 == 0) {
                        System.out.println("已处理音频帧: " + count);
                        System.gc();
                    }
                }
                // 立即释放音频帧资源
                if (audioFrame != null) {
                    audioFrame.close();
                }
            }
            System.out.println("音频处理完成，共处理 " + count + " 帧");
        } catch (Exception e) {
            System.err.println("复制音频轨道失败: " + e.getMessage());
        } finally {
            if (audioGrabber != null) {
                try {
                    audioGrabber.stop();
                    audioGrabber.release();
                } catch (Exception e) {
                    System.err.println("释放音频抓取器失败: " + e.getMessage());
                }
            }
        }
    }
}